﻿#pragma once
#include "yzrutil.h"
#include "ByteOrder.h"

#include "array/Array.hpp"
#include "lang/Exception.h"

namespace yzrilyzr_io{
	EBCLASS(ByteBuffer){
	private:
	yzrilyzr_array::ByteArray hb;
	u_index _mark=-1;
	u_index _position=0;
	u_index _limit=0;
	u_index _capacity=0;
	u_index _offset=0;
	bool bigEndian=false;
	public:
	ByteBuffer(u_index mark, u_index pos, u_index lim, u_index cap);
	ByteBuffer(u_index mark, u_index pos, u_index lim, u_index cap, const yzrilyzr_array::ByteArray & hb, u_index offset);
	private:
	static yzrilyzr_lang::Exception createCapacityException(u_index capacity);
	yzrilyzr_lang::Exception createPositionException(u_index newPosition);
	yzrilyzr_lang::Exception createLimitException(u_index newLimit);
	u_index nextGetIndex();
	u_index nextGetIndex(u_index nb);
	u_index ix(u_index i);
	ByteBuffer & getArray(u_index index,const yzrilyzr_array::ByteArray & dst, u_index offset, u_index length);
	u_index checkIndex(u_index i, u_index nb);
	u_index checkIndex(u_index i);
	u_index byteOffset(u_index i);
	u_index nextPutIndex();
	u_index nextPutIndex(u_index nb);
	public:
	static std::shared_ptr<ByteBuffer> wrap(const yzrilyzr_array::ByteArray & buf);
	static std::shared_ptr<ByteBuffer> wrap(const yzrilyzr_array::ByteArray & buf, u_index off, u_index len);
	static std::shared_ptr<ByteBuffer> allocate(u_index len);
	int8_t get();
	int8_t get(u_index i);
	int16_t getShort();
	int16_t getShort(u_index index);
	int32_t getInt();
	int32_t getInt(u_index index);
	int64_t getLong();
	int64_t getLong(u_index index);
	ByteBuffer & put(int8_t x);
	ByteBuffer & put(u_index i, int8_t x);
	ByteBuffer & put(const yzrilyzr_array::ByteArray & x);
	ByteBuffer & put(const yzrilyzr_array::ByteArray & src, u_index offset, u_index length);
	ByteBuffer & putShort(u_index i, int16_t x);
	ByteBuffer & putShort(int16_t x);
	ByteBuffer & putInt(u_index i, int32_t x);
	ByteBuffer & putInt(int32_t x);
	ByteBuffer & putLong(u_index i,int64_t x);
	ByteBuffer & putLong(int64_t x);
	ByteBuffer & order(ByteOrder order);
	u_index limit();
	ByteBuffer & limit(u_index newLimit);
	u_index capacity()const;
	u_index position()const;
	ByteBuffer & position(u_index newPosition);
	ByteBuffer & get(const yzrilyzr_array::ByteArray & dst);
	ByteBuffer & get(const yzrilyzr_array::ByteArray & dst, u_index offset, u_index length);
	yzrilyzr_array::ByteArray array();
	};
}